﻿using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WAU.Models.Framework;

namespace WAU.Utilities.Redis
{
    /// <summary>
    /// Redis 客户端 Service
    /// </summary>
    public class RedisClientService
    {
        /// <summary>
        /// Redis 客户端
        /// </summary>
        public static ConnectionMultiplexer RedisClient = ConnectionMultiplexer.Connect(GlobalConfig.Setting.ConnectionStrings.Redis);

        /// <summary>
        /// Redis 数据库
        /// </summary>
        public static IDatabase RedisDB = RedisClient.GetDatabase(0);

        private const string DISTRIBUTED_LOCK_CACHE_TAG = "DLOCK";

        /// <summary>
        /// 尝试获取分布式锁
        /// </summary>
        /// <param name="key"></param>
        /// <param name="expireSeconds"></param>
        /// <returns></returns>
        public static bool TryGetDistributedLock(string key, int expireSeconds = 10)
        {
            return RedisDB.StringSet($"{DISTRIBUTED_LOCK_CACHE_TAG}:{key}", "1", TimeSpan.FromSeconds(10), false, When.NotExists, CommandFlags.None);
        }

        /// <summary>
        /// 尝试解除分布式锁
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static bool TryReleaseDistributedLock(string key)
        {
            return RedisDB.KeyDelete($"{DISTRIBUTED_LOCK_CACHE_TAG}:{key}");
        }

        #region Lua 脚本

        /// <summary>
        /// 创建订单判断 脚本
        /// </summary>
        public static LoadedLuaScript OrderJudgeScript;

        static RedisClientService()
        {
            IServer server = RedisClient.GetServers()[0];

            LuaScript luaOrderJudgeScript = LuaScript.Prepare(@" 
                                -- 1. 参数列表
                                -- 1.1 优惠券 id
                                local skuId = @skuId
                                -- 1.2 用户id
                                local userId = @userId

                                -- 2.数据key
                                -- 2.1 库存key
                                local stockKey = 'order:stock:' .. skuId
                                -- 2.2 订单key
                                local orderKey = 'order:orders:' .. userId

                                -- 3.脚本业务
                                -- 3.1 判断库存是否充足 get stockKey
                                if (tonumber(redis.call('GET', stockKey)) < 0) then
                                    -- 3.2 库存不足，返回 1
                                    return 1
                                end

                                -- 3.3 判断用户是否下单 SISMEMBER orderKey userId
                                if (redis.call('SISMEMBER', orderKey, userId) == 1) then
                                    -- 3.4 存在，说明是重复下单，返回 2
                                    return 2
                                end

                                -- 3.5 扣库存
                                redis.call('INCRBY', stockKey, @skuCount)

                                -- 3.6 保存用户
                                redis.call('SADD', orderKey, userId)

                                return 0");

            OrderJudgeScript = luaOrderJudgeScript.Load(server);
        }

        #endregion
    }
}
